/* Scanner.cpp
 * Purpose: To scan and pass characters to Tokenizer
 *
 * Description: This class creates a file stream. It then feeds lines and characters to the Tokenizer as it is called
 * 				It also handles printing.
 */

#include <iostream>
#include <stdio.h>
#include "Scanner.h"
using namespace std;


Scanner::Scanner(const string & file) {

	const char * fName = file.c_str();
	fileName = file;
	sourceFile = fopen(fName, "r");
	//sourceLine = "";
	sourceLineIndex = 256;
	pageNumber = 1;
	lineNumber = 1;

}

// Public Functions:
void Scanner::ScanFile( Tokenizer & token) {

	PrintPageHeader();
	while(FetchSourceLine()){
		PrintLine();
		while (token.FetchToken()){
			PrintToken(token);
		}
	}

}

void Scanner::BackUpCharacter() {

	sourceLineIndex--;
	cout << "Index is now: " << sourceLineIndex << endl;

}

char Scanner::FetchCharacter() {

	cout << "Fetching a character...\n";
	if (sourceLineIndex == MAX_SOURCE_LINE_LENGTH) {
		FetchSourceLine();
		return sourceChars[sourceLineIndex];

	}
	else if(sourceChars[sourceLineIndex] == '{') {
		SkipComment();
		//cout << sourceChars[sourceLineIndex] << endl;
		char srcChar = sourceChars[sourceLineIndex];
		sourceLineIndex++;
		return srcChar;
	}
	else {
		//cout << sourceChars[sourceLineIndex] << endl;
		char srcChar = sourceChars[sourceLineIndex];
		cout << "Fetched a character: " << srcChar << "\n";
		sourceLineIndex++;
		cout << "Index is now: " << sourceLineIndex << endl;
		return srcChar;
	}

}

// Private Functions:
bool Scanner::FetchSourceLine() {

	//char sourceArray[MAX_SOURCE_LINE_LENGTH];
	for (int i = 0; i < 256; i++)
		sourceChars[i] = 0;
	if(fgets(sourceChars, MAX_SOURCE_LINE_LENGTH, sourceFile) == NULL){
	         return false;
	}
	else{
		//cout << sourceChars << endl;
		//sourceLine = sourceArray;
		sourceLineIndex = 0;
		return true;
	}

}

void Scanner::SkipComment() {

	while (sourceChars[sourceLineIndex] != '}')
				sourceLineIndex++;

}

void Scanner::PrintLine()
{
	cout << lineNumber << ": " << sourceChars;
	lineNumber++;
}

void Scanner::PrintToken(Tokenizer & token) {
	char delim = 0;
	string tokenStr = token.GetTokenString();
	char tStr[tokenStr.length()];
	for (int i = 0; i < tokenStr.length(); i++)
		tStr[i] = tokenStr[i];
	if (tStr[0] != delim)
		cout << ">> " << token.GetTokenCode() << "\t" << token.GetTokenString() << "\n";
}

void Scanner::PrintPageHeader()
{
	time_t t = time (0);
	struct tm * now = localtime( & t);
	cout << "Page " << pageNumber << "\t" << fileName << "\t" << asctime(now) << endl;
	pageNumber++;
	lineNumber = 1;
}

Scanner::~Scanner() {
	fclose(sourceFile);
}
